package com.groupdocs.viewer.resources;

import com.groupdocs.viewer.config.Config;
import com.groupdocs.viewer.config.ServiceConfiguration;
import com.groupdocs.viewer.domain.path.EncodedPath;
import com.groupdocs.viewer.domain.path.GroupDocsPath;
import com.groupdocs.viewer.domain.path.TokenId;
import com.groupdocs.viewer.handlers.ViewerHandler;
import com.groupdocs.viewer.views.ViewerView;
import com.sun.jersey.multipart.FormDataParam;
import org.json.JSONException;
import org.json.JSONObject;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;

/**
 *
 * @author Alex Bobkov
 */

@Path(value = "")
public class ViewerResource extends GroupDocsViewer implements IGroupDocsViewer, IGroupDocsViewerIE{
    public static final String RENDERING_MODE_IMAGE = "image";
    public static final String RENDERING_MODE_HTML = "html";
    private final ViewerHandler viewerHandler;
    private final Config configuration;
    
    public ViewerResource(Config configuration){
        this.configuration = configuration;
        ServiceConfiguration config = new ServiceConfiguration(configuration);
        //Uncomment this line to use Azure storage
        //viewerHandler = new ViewerHandler(config, new AzureInputDataHandler("acount_name", "account_key"));
        //Uncomment this line to use Amazon S3 storage
        //viewerHandler = new ViewerHandler(config, new AmazonS3InputDataHandler("access_key", "secret_key", "bucket_name"));
        viewerHandler = new ViewerHandler(config/*, new CustomInputDataHandler(config)*/ /*, new CustomHtmlCacheHandler(configuration.getCachePath()) */);
    }

    @GET
    public ViewerView getViewer(@QueryParam("rendering") String renderingMode) throws Exception {
        return getView("", configureRenderingMode(renderingMode));
    }

    @GET
    @Path(value = VIEW)
    public ViewerView getView(@QueryParam("file") String file,
                              @QueryParam("tokenId") String tokenId,
                              @QueryParam("rendering") String renderingMode) throws Exception{
        GroupDocsPath path = null;
        if(file != null && !file.isEmpty()){
            path = new EncodedPath(file, viewerHandler.getConfiguration());
        }else if(tokenId != null && !tokenId.isEmpty()){
            TokenId tki = new TokenId(tokenId, configuration.getEncryptionKey());
            if(!tki.isExpired()){
                path = tki;
            }
        }
        return getView((path == null) ? "" : path.getPath(), configureRenderingMode(renderingMode));
    }
    
    private ViewerView getView(String filePath, String renderingMode) throws Exception{
        try {
            String viewerId = "test";
            String locale = viewerHandler.getLocale();
            return new ViewerView(viewerHandler.getHeader(), viewerHandler.getViewerScript(viewerId, filePath, locale),
                    renderingMode);
        } catch (IOException ex) {
            return null;
        }
    }

    private String configureRenderingMode(String renderingMode) {
        if (RENDERING_MODE_IMAGE.equals(renderingMode)) {
            ((Config)viewerHandler.getConfiguration().getConfig()).setUseHtmlBasedEngine(false);
            return RENDERING_MODE_IMAGE;
        }
        ((Config)viewerHandler.getConfiguration().getConfig()).setUseHtmlBasedEngine(true);
        return RENDERING_MODE_HTML;
    }
    
    @GET
    @Path(value = GET_JS_HANDLER)
    @Override
    public Object getJsHandler(@QueryParam("script") String scriptName, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception{
        Object obj = viewerHandler.getJsHandler(scriptName, request, response);
        //caching resources
        if(obj != null){
            return obj;
        }else{
            return Response.status(Response.Status.NOT_MODIFIED).build();
        }
    }

    @GET
    @Path(value = GET_CSS_HANDLER)
    @Override
    public Object getCssHandler(@QueryParam("script") String cssName, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception{
        Object obj = viewerHandler.getCssHandler(cssName, request, response);
        //caching resources
        if(obj != null){
            return obj;
        }else{
            return Response.status(Response.Status.NOT_MODIFIED).build();
        }
    }

    @GET
    @Path(value = GET_IMAGE_HANDLER)
    @Override
    public Object getImageHandler(@PathParam("name") String imageName, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception{
        Object obj = viewerHandler.getImageHandler(imageName, request, response);
        //caching resources
        if(obj != null){
            return obj;
        }else{
            return Response.status(Response.Status.NOT_MODIFIED).build();
        }
    }
    
    @GET
    @Path(value = GET_FONT_HANDLER)
    @Override
    public Object getFontHandler(@PathParam("name") String fontName, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception{
        Object obj = viewerHandler.getFontHandler(fontName, request, response);
        //caching resources
        if(obj != null){
            return obj;
        }else{
            return Response.status(Response.Status.NOT_MODIFIED).build();
        }
    }
    
    @GET
    @Path(value = GET_HTML_RESOURCES_HANDLER)
    @Override
    public Object getHtmlResourcesHandler(@QueryParam("filePath") String filePath, @QueryParam("guid") String guid, @QueryParam("page") Integer page, @QueryParam("resourceName") String resourceName, @Context HttpServletResponse response) throws Exception{
        return viewerHandler.getHtmlResourcesHandler(filePath, guid, page, resourceName, response);
    }

    @GET
    @Path(value = GET_FILE_HANDLER)
    @Override
    public Object getFileHandler(@QueryParam("path") String path, @QueryParam("getPdf") boolean getPdf, @Context HttpServletResponse response) throws Exception{
        return viewerHandler.getFileHandler(path, getPdf, response);
    }

    @GET
    @Path(value=GET_DOCUMENT_PAGE_IMAGE_HANDLER)
    @Override
    public Object getDocumentPageImageHandler(@QueryParam("path") String path, @QueryParam("width") Integer width, @QueryParam("quality") Integer quality, @QueryParam("usePdf") Boolean usePdf, @QueryParam("pageIndex") Integer pageIndex, @QueryParam("isPrint") Boolean isPrint, @Context HttpServletResponse response) throws Exception{
        return viewerHandler.getDocumentPageImageHandler(path, width, quality, usePdf, pageIndex, isPrint, response);
    }

    @POST
    @Path(value = VIEW_DOCUMENT_HANDLER)
    @Override
    public Object viewDocumentHandler(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.viewDocumentHandler(request, response);
    }

    @GET
    @Path(value = VIEW_DOCUMENT_HANDLER)
    @Override
    public Object viewDocumentHandler(@QueryParam("callback") String callback, @QueryParam("data") String data, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.viewDocumentHandler(callback, data, request, response);
    }

    @POST
    @Path(value = LOAD_FILE_BROWSER_TREE_DATA_HANLER)
    @Override
    public Object loadFileBrowserTreeDataHandler(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.loadFileBrowserTreeDataHandler(request, response);
    }

    @GET
    @Path(value=LOAD_FILE_BROWSER_TREE_DATA_HANLER)
    @Override
    public Object loadFileBrowserTreeDataHandler(@QueryParam("callback") String callback, @QueryParam("data") String data, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.loadFileBrowserTreeDataHandler(callback, data, response);
    }

    @POST
    @Path(value = GET_IMAGE_URL_HANDLER)
    @Produces(MediaType.APPLICATION_JSON)
    @Override
    public Object getImageUrlsHandler(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.getImageUrlsHandler(request, response);
    }

    @GET
    @Path(value = GET_IMAGE_URL_HANDLER)
    @Produces(MediaType.APPLICATION_JSON)
    @Override
    public Object getImageUrlsHandler(@QueryParam("callback") String callback, @QueryParam("data") String data, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.getImageUrlsHandler(callback, data, request, response);
    }

    @POST
    @Path(value = GET_PRINTABLE_HTML_HANDLER)
    @Produces(MediaType.APPLICATION_JSON)
    @Override
    public Object getPrintableHtmlHandler(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.getPrintableHtmlHandler(request, response);
    }

    @GET
    @Path(value = GET_PRINTABLE_HTML_HANDLER)
    @Produces(MediaType.APPLICATION_JSON)
    @Override
    public Object getPrintableHtmlHandler(@QueryParam("callback") String callback, @QueryParam("data") String data, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.getPrintableHtmlHandler(callback, data, request, response);
    }
    
    @POST
    @Path(value = UPLOAD_FILE)
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public void uploadFileHandler(@FormDataParam("file") InputStream inputStream,
                                  @FormDataParam("fileName") String fileName,
                                  @FormDataParam("rendering") String renderingMode,
                                  @Context HttpServletResponse response) throws IOException, JSONException, Exception{
        // Upload file
        String uploadResponse = (String) viewerHandler.uploadFile(inputStream, fileName, configuration.getExpirationDate());
        // Convert upload response to json object
        JSONObject obj = new JSONObject(uploadResponse);
        // Get token id
        String tokenId = obj.getString("tokenId");
        // Redirect to uplaoded file
        response.sendRedirect(VIEW + "?tokenId=" + tokenId + "&rendering=" + renderingMode);
    }

    @POST
    @Path(value = "UploadFileAPI")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Object uploadFileHandler(@FormDataParam("file") InputStream inputStream, @FormDataParam("fileName") String fileName) throws Exception{
        return viewerHandler.uploadFile(inputStream, fileName, configuration.getExpirationDate());
    }
    
    @GET
    @Path(value = "RenewToken")
    public Object renewTokenId(@QueryParam("tokenId") String tokenId){
        return viewerHandler.renewTokenId(tokenId);
    }
    
    @POST
    @Path(value = GET_DOCUMENT_PAGE_HTML_HANDLER)
    @Override
    public Object getDocumentPageHtmlHandler(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception{
        return viewerHandler.getDocumentPageHtmlHandler(request, response);
    }

    @GET
    @Path(value = GET_PDF_WITH_PRINT_DIALOG)
    @Override
    public void getPdfWithPrintDialog(@QueryParam("path") String path, @Context HttpServletResponse response) throws Exception{
        viewerHandler.getPdfWithPrintDialog(path, response);
    }

    @POST
    @Path(value = REORDER_PAGE_HANDLER)
    @Override
    public Object reorderPageHandler(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception{
        return viewerHandler.reorderPageHandler(request, response);
    }

    @POST
    @Path(value = ROTATE_PAGE_HANDLER)
    @Override
    public Object rotatePageHandler(@Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception {
        return viewerHandler.rotatePageHandler(request, response);
    }
}
